package ntut.andengine.physics;

import java.util.ArrayList;
import java.util.List;

import javax.microedition.khronos.opengles.GL10;

import ntut.andengine.events.Command;
import ntut.andengine.events.UpdateCommand;
import ntut.andengine.events.UpdateEmitter;
import ntut.andengine.game.GameLevel;
import ntut.andengine.gamedesign.GameSceneLevel;

import org.anddev.andengine.entity.particle.ParticleSystem;
import org.anddev.andengine.entity.particle.emitter.CircleParticleEmitter;
import org.anddev.andengine.entity.particle.initializer.VelocityInitializer;
import org.anddev.andengine.entity.particle.modifier.ColorModifier;
import org.anddev.andengine.entity.particle.modifier.ExpireModifier;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.extension.physics.box2d.PhysicsConnector;
import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.bitmap.BitmapTexture;
import org.anddev.andengine.opengl.texture.bitmap.BitmapTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;

import android.util.Log;
import android.widget.Toast;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.Filter;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;

public class Player extends PhysicalComponent {

	private ColorModifier colorModifier;
	private ParticleSystem particleSystem;
	private CircleParticleEmitter particleEmitter;
	private GameLevel mLevel;
	float deadCounter;
	boolean isAnimation = false;
	private List<Body> upList;
	private List<Body> downList;
	private List<Body> leftList;
	private List<Body> rightList;

	public Player(GameLevel level) {
		super(level);

		mLevel = level;

		upList = new ArrayList<Body>();
		downList = new ArrayList<Body>();
		leftList = new ArrayList<Body>();
		rightList = new ArrayList<Body>();

		this.mBitmapTexture = new BitmapTexture(64, 32,
				TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		TextureRegion sparkleTextureRegion = BitmapTextureRegionFactory
				.createFromAsset(this.mBitmapTexture, level, "sparkle.png", 0,
						0);
		TextureRegion particleTextureRegion = BitmapTextureRegionFactory
				.createFromAsset(this.mBitmapTexture, level,
						"particle_small_point.png", 32, 0);
		level.getEngine().getTextureManager().loadTexture(this.mBitmapTexture);

		mSprite = new Sprite(0, 0, sparkleTextureRegion);
		mSprite.setScale(0.9f);

		FixtureDef fixtureDef = PhysicsFactory.createFixtureDef(1, 0, 0);
		mBody = PhysicsFactory.createBoxBody(level.getPhysicsWorld(), mSprite,
				BodyType.DynamicBody, fixtureDef);
		mBody.setUserData(new ContactEvent("Player") {

			@Override
			public void beginContact(Body body, Vector2 normal) {

				boolean wallTrap = false;
				if (normal.x > 0.9){
	                rightList.add(body);
	                Log.d("R", body.getLinearVelocity().toString());
	                try{
	                	if(body.getUserData().toString() == "Wall") wallTrap = true;
	                	else wallTrap = false;
	                }catch(Exception e){
						e.printStackTrace();
					}
	                
	            }
	            if (normal.x < -0.9){
	                leftList.add(body);
	                Log.d("L", body.getLinearVelocity().toString());
	                try{
		                if(body.getUserData().toString() == "Wall") wallTrap = true;
		                else wallTrap = false;
	                }catch(Exception e){
						e.printStackTrace();
					}
	            }
	            if (normal.y > 0.9){
	                downList.add(body);
	                Log.d("D", body.getLinearVelocity().toString());
	                try{
		                if(body.getUserData().toString() == "Wall") wallTrap = true;
		                else wallTrap = false;   
	                }catch(Exception e){
						e.printStackTrace();
					}
	            }
	            if(normal.y < -0.9){
	                upList.add(body);
	                Log.d("U", body.getLinearVelocity().toString());
	                try{
		                if(body.getUserData().toString() == "Wall") wallTrap = true;
		                else wallTrap = false;
	                }catch(Exception e){
						e.printStackTrace();
					}
	            }
	            if (rightList.size() > 0 && leftList.size() > 0 || upList.size() > 0 && downList.size() > 0){
	            	Vector2 velocity = body.getLinearVelocity();
	            	if(wallTrap || velocity.x < -0.3 || velocity.x > 0.3 || velocity.y < -0.3 || velocity.y > 0.3)
	            		DeadAnimationStart();
	            }
	            
				try{
					if(body.getUserData().toString() == "DeathLight"){
						mLevel.addCommand(new Command(){

							@Override
							public void executeCommand() {
								DeadAnimationStart();
							}

						});
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			@Override
			public void endContact(Body body, Vector2 Normal) {
				rightList.remove(body);
				leftList.remove(body);
				upList.remove(body);
				downList.remove(body);
			}

		});
		mBody.setFixedRotation(true);

		level.getScene().attachChild(mSprite);
		level.getPhysicsWorld().registerPhysicsConnector(
				new PhysicsConnector(mSprite, mBody, true, true));

		setSparkleParticleSystem(level, particleTextureRegion);

		level.addMovingComponent(this);
		level.addUpdateCommand(new UpdateCommand() {

			@Override
			public void updateCommand(float pSecondsElapsed) {
				DeadAnimationCounter(pSecondsElapsed);

			}

		});
	}

	public void DeadAnimationStart() {

		if (!isAnimation) {

			deadCounter = 0;
			isAnimation = true;
			particleSystem.removeParticleModifier(colorModifier);
			particleSystem.setParticlesSpawnEnabled(false);
			mBody.setType(BodyType.StaticBody);

			mLevel.runOnUiThread(new Runnable() {

				@Override
				public void run() {
					mLevel.getEngine().vibrate(200);
					Toast.makeText(mLevel, "You failed...", Toast.LENGTH_SHORT)
							.show();
				}

			});
		}
	}

	private void DeadAnimationCounter(float time) {
		if (isAnimation) {
			deadCounter += time;
			if (deadCounter > 2) {
				DeadAnimationEnd();
			}
		}
	}

//<<<<<<< .mine
	public void DeadAnimationEnd() {
		isAnimation = false;

		particleSystem.addParticleModifier(colorModifier);
		particleSystem.setParticlesSpawnEnabled(true);

//		mBody.setType(BodyType.DynamicBody);
//		mLevel.recoveryPosition();
//	}
//
//=======
        mBody.setType(BodyType.DynamicBody);
        mLevel.recoveryPosition();
        mLevel.recoveryBox(mLevel.getPhysicsWorld());///////////////////////////////////////////////////////////////////////////////
    }
	
//>>>>>>> .r41
	public void changeColor(ComponentColor color) {
		setColor(color);
		Filter filter = new Filter();

		switch (color) {
		case White:
			particleSystem.removeParticleModifier(colorModifier);
			colorModifier = new ColorModifier(1, 0, 1, 0, 1, 0, 0, 1);
			particleSystem.addParticleModifier(colorModifier);
			mSprite.setColor(1, 1, 1);
			filter.categoryBits = GameSceneLevel.CATEGORYBIT_WHITE;
			filter.maskBits = GameSceneLevel.MASKBITS_WHITE;
			for (Fixture f : mBody.getFixtureList()) {
				f.setFilterData(filter);
			}
			break;
		case Red:
			particleSystem.removeParticleModifier(colorModifier);
			colorModifier = new ColorModifier(1, 0, 0, 0, 0, 0, 0, 1);
			particleSystem.addParticleModifier(colorModifier);
			mSprite.setColor(1, 0.1f, 0.1f);

			for (PhysicalComponent component : mLevel
					.getPhysicalComponentList()) {
				component.changeToRed();
			}
			filter.categoryBits = GameSceneLevel.CATEGORYBIT_RED;
			filter.maskBits = GameSceneLevel.MASKBITS_RED;
			for (Fixture f : mBody.getFixtureList()) {
				f.setFilterData(filter);
			}
			break;
		case Blue:
			particleSystem.removeParticleModifier(colorModifier);
			colorModifier = new ColorModifier(0, 0, 0, 0, 1, 0, 0, 1);
			particleSystem.addParticleModifier(colorModifier);
			mSprite.setColor(0.1f, 0.1f, 1);

			for (PhysicalComponent component : mLevel
					.getPhysicalComponentList()) {
				component.changeToBlue();
			}
			filter.categoryBits = GameSceneLevel.CATEGORYBIT_BLUE;
			filter.maskBits = GameSceneLevel.MASKBITS_BLUE;
			for (Fixture f : mBody.getFixtureList()) {
				f.setFilterData(filter);
			}
			break;
		}
	}

	private void setSparkleParticleSystem(GameLevel level,
			TextureRegion particleTextureRegion) {

		particleEmitter = new CircleParticleEmitter(100, 100, 16);
		particleSystem = new ParticleSystem(particleEmitter, 100, 100, 1000,
				particleTextureRegion);
		particleSystem.addParticleInitializer(new VelocityInitializer(-16, 16,
				-16, 16)); // opening animation
		colorModifier = new ColorModifier(1, 0, 0, 0, 0, 0, 0, 1);
		particleSystem.addParticleModifier(colorModifier);
		// particleSystem.addParticleModifier(new AlphaModifier(1, 0, 0, 1));
		particleSystem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
		particleSystem.addParticleModifier(new ExpireModifier(2, 2));

		level.getScene().attachChild(particleSystem);

		level.addSparkleListener(new UpdateEmitter() {

			@Override
			public void onUpdateEmitterEvent() {

				particleEmitter.setCenter(mSprite.getX() + mSprite.getWidth()
						/ 4, mSprite.getY() + mSprite.getHeight() / 4);
			}

		});
	}
}
